#ifndef ASTAR_H
#define ASTAR_H

#include <QHash>
#include <QLinkedList>
#include <QSet>

#include "geometry/edge3d.h"
#include "global/typedef.h"

class QVector3D;

class AStar
{
public:
    static AStar* instance();

    QLinkedList< const QVector3D* > run(const Graph& rkGraph,
                                        const QVector3D& rkStart,
                                        const QVector3D& rkEnd);

protected:
    AStar();
    ~AStar();

    AStar(const AStar&);
    AStar& operator = (const AStar&);

private:
    static float estimate(const QVector3D& rkStart, const QVector3D& rkEnd);

    void init();
    void clear();
    const QVector3D& next() const;
    QLinkedList< const QVector3D* > build() const;
    QSet< const QVector3D* > neighbours(const QVector3D& rkOrigin) const;
    float g(const QVector3D& rkVertex) const;
    float f(const QVector3D& rkVertex) const;

    //------------------------------------------------
    //  Attributes.
    //------------------------------------------------
    // Singleton instance.
    static AStar*                               s_pkInstance;

    // Graph data.
    const Graph*                                m_pkGraph;

    const QVector3D*                            m_pkStart;
    const QVector3D*                            m_pkEnd;

    // AStar algorithm data.
    QHash< const QVector3D*, const QVector3D* > m_kParents;
    QSet< const QVector3D* >                    m_kClosed;
    QSet< const QVector3D* >                    m_kOpened;
    QHash< const QVector3D*, float >            m_kGCost;
    QHash< const QVector3D*, float >            m_kFCost;
};

#endif // ASTAR_H
